#include "gb.h"
#include "GUI.h"
#include <stdio.h>
#include <stdlib.h>

int defaultEventFilter(const SDL_Event *event);

int GUI_run(gb_state *gb, char *fileName)
{
    // For Timing
	unsigned int start = 0, delta = 0, cyclesPerFrame = 0;
	// The whole window
	SDL_Surface *window = 0;
	// The game image
	SDL_Surface *image = 0;
	// Position of the image on the window
	SDL_Rect windowPos;

	SDL_Event event;
	int quit = 0;

    if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
    {
        fprintf(stderr, "SDL could not init\n");
        exit(1);
    }

	windowPos.x = 0;
	windowPos.y = 0;

	window = SDL_SetVideoMode(PIXELX, PIXELY,
                           32, SDL_SWSURFACE | SDL_RESIZABLE);
	if(!window)
	{
	    fprintf(stderr, "Couldn't create window\n");
	    exit(1);
	}
	image = SDL_CreateRGBSurface(SDL_SWSURFACE, PIXELX, PIXELY,
            32, RMASK, GMASK, BMASK, 0);
    if(!image)
    {
        fprintf(stderr, "Couldn't create image\n");
        exit(1);
    }

    // The gb gpu will draw directly onto the surface
	gb->gpu_state.screen = (unsigned char *)image->pixels;
    gb->gpu_state.screenw = PIXELX;
    gb->gpu_state.screenh = PIXELY;

    // Number of gameboy cycles exected between
    //  frames
    cyclesPerFrame = gb->cpu_freq / gb->gpu_state.fps;
    // This is the main loop
	while(!quit)
	{
		start = SDL_GetTicks();
		gb_cpu_execute(gb, cyclesPerFrame);

		// Draw game image
		SDL_BlitSurface(image, 0, window, &windowPos);
		SDL_UpdateRect(window, 0, 0,
                gb->gpu_state.screenw, gb->gpu_state.screenh);

		delta = SDL_GetTicks() - start;
		if(delta < 1000 / gb->gpu_state.fps)
		{
			SDL_Delay((1000/gb->gpu_state.fps) - delta);
		}

		while(SDL_PollEvent(&event))
		{
            switch(event.type)
            {
                case SDL_QUIT:
                    // Save the current RAM
                    {
                        FILE * ramSave = 0;
                        // Add 5 chars for ".sav"
                        char * saveName =
                                malloc(sizeof(char)*strlen(fileName)+5);
                        strcpy(saveName, fileName);
                        strcat(saveName, ".sav");
                        ramSave = fopen(saveName, "wb");
                        if(ramSave)
                        {
                            if(fwrite(gb->eram, 1, gb->eram_size, ramSave)
                                    != gb->eram_size)
                            {
                                remove(saveName);
                            }
                            fclose(ramSave);
                        }
                        free(saveName);
                    }
                    quit = 1;
                    break;
                case SDL_VIDEORESIZE:
                    // Don't allow the window to become
                    // smaller than its original size
                    if(event.resize.w < PIXELX)
                        event.resize.w = PIXELX;
                    if(event.resize.h < PIXELY)
                        event.resize.h = PIXELY;

                    if((window =
                            SDL_SetVideoMode(event.resize.w, event.resize.h,
                            32, SDL_SWSURFACE | SDL_RESIZABLE))
                       == NULL)
                    {
                        fprintf(stderr, "Window resize failed\n");
                        exit(1);
                    }
                    SDL_FreeSurface(image);
                    if((image = SDL_CreateRGBSurface(SDL_SWSURFACE,
                            event.resize.w, event.resize.h,
                            32, RMASK, GMASK, BMASK, 0)) == NULL)
                    {
                        fprintf(stderr, "Window resize failed\n");
                        exit(1);
                    }
                    gb->gpu_state.screen = (unsigned char *)image->pixels;
                    gb->gpu_state.screenw = event.resize.w;
                    gb->gpu_state.screenh = event.resize.h;
                    break;
                case SDL_MOUSEBUTTONDOWN:
                    break;
            }
		}
	}

	SDL_FreeSurface(window);
	SDL_FreeSurface(image);

	SDL_Quit();
	return 0;
}
